/*
 * 教材中的示例程序之完整版.
 * 书名：《编译原理基础》
 * 版次：第三版
 * 作者：王献青，张立勇，张淑平，刘坚
 * 出版社：西安电子科技大学出版社
 * 程序完成时间：2025.03
 */

//
// 文件内容：直接编码的识别函数1
//

#include <stdio.h>

#include "lexer.h"

//直接编码的识别函数1: 基于状态变量及其变化的实现
//::  教材程序清单2.2
TokenKind recognize_word_direct_coded_1()
{
    // 从初态开始反复向前扫描（匹配），直到输入结束，
    // 或单词结束，或发现一个错误
    int state = 0;
    for ( ; ! IS_EOF(*forward); ++forward ) {

        char c = *forward;                // 当前字符
        switch ( state ) {                // 第1层分情况：当前状态
            case 0:   // 当前状态为0
                if ( c == '<' ) state = 1;  // 第2层分情况：输入字符
                else if ( c == '!' ) state = 3;
                else if ( c == '=' ) state = 5;
                else if ( c == '>' ) state = 7;
                else if ( IS_LETTER(c) ) state = 10; // c是字母或下划线
                else if ( IS_DIGIT (c) ) state = 12; // c是数字字符
                else return ERROR;  // 第1个字符无效，直接返回错误
                continue;
            case 1:   // 当前状态为1
                if ( c == '=' )   return LE;      // state 2，单词结束
                else { --forward; return LT; }    // 退回其他字符，返回LT
            case 3:   // 当前状态为3
                if ( c == '=' )   return NE;      // state 4，单词结束
                else { --forward; return NOT; }   // 退回其他字符，返回NOT
            case 5:   // 当前状态5
                if ( c == '=' )   return EQ;      // state 6，单词结束
                else { --forward; return ASSIGN; } // 退回其他字符，返回ASSIGN
            case 7:   // 当前状态为7
                if ( c == '=' )   return GE;      // state 8，单词结束
                else { --forward; return GT; }    // 退回其他字符，返回GT
            case 10:  // 当前状态为10
                if ( IS_LETTER (c) ) state = 10;     // 状态图中的环
                else if ( IS_DIGIT (c) ) state = 10; // 状态图中的环
                else { --forward; return ID; }   // 退回其他字符，返回ID
                continue;
            case 12:  // 当前状态为12
                if ( c == '.' ) state = 13;
                else if ( c == 'E' ) state = 15;
                else if ( IS_DIGIT (c) ) state = 12; // 状态图中的环
                else { --forward; return INT; } // 退回其他字符，返回INT
                continue;
            case 13:  // 当前状态为13
                if ( IS_DIGIT (c) ) state = 14;
                else {  // 小数点后面不是数字的处理
                    // 这里的处理仅为演示：有些应用中，需要状态回退到
                    //   最近一次经历的终态
                    --forward; --forward;
                    return INT;  // 接受整数部分
                }
                continue;
            case 14:  // 状态14 对应的程序结构与状态12相似
                if ( IS_DIGIT (c) ) state = 14;
                else if ( c == 'E' ) state = 15;
                else { --forward; return REAL; } // 退回其他字符，返回REAL
                continue;
            case 15:
                if ( c == '+' || c == '-'  ) state = 16;
                else if ( IS_DIGIT (c) ) state = 17;
                else { return ERROR; } // 指数部分的E后面的字符无效，直接返回错误
                continue;
            case 16:
                if ( IS_DIGIT (c) ) state = 17;
                else { return ERROR; } // 指数部分的正负号后面的字符无效，直接返回错误
                continue;
            case 17:
                if ( IS_DIGIT (c) ) state = 17;
                else {  --forward; return REAL; }
            default:
                fprintf(stderr, "BUG: bad state %d\n", state);
                return ERROR;
        }  // switch(state) 结束
    }      // for 循环结束

    //到达输入结束了其仍未确定单词的结束，则需要
    //   根据当前状态 确定返回对应的记号种类
    switch(state) {
        case 0  : return EOFS; // 通知调用者：输入已分析结束
        case 10 : return ID;
        case 12 : return INT;
        case 14 : case 17 : return REAL;
        default : return ERROR;
    }
}
